/* 
 *************************************
 * <!-- 3D Filmic Effects -->
 *************************************
 */
import {
    templateUrl,
    homeUrl,
    ajaxUrl,
    browser,
    UixModuleInstance,
    UixGUID,
    UixMath,
    UixCssProperty
} from '@uixkit/core/_global/js';


//filter basic
//---------------------
import EffectComposer from '@uixkit/plugins/THREE/postprocessing/EffectComposer';
import MaskPass from '@uixkit/plugins/THREE/postprocessing/MaskPass';
import TexturePass from '@uixkit/plugins/THREE/postprocessing/TexturePass';
import ShaderPass from '@uixkit/plugins/THREE/postprocessing/ShaderPass';
import RenderPass from '@uixkit/plugins/THREE/postprocessing/RenderPass';
import ClearPass from '@uixkit/plugins/THREE/postprocessing/ClearPass';
import CopyShader from '@uixkit/plugins/THREE/shaders/CopyShader';
import ConvolutionShader from '@uixkit/plugins/THREE/shaders/ConvolutionShader';


//Extra filter -- film
//---------------------
import BloomPass from '@uixkit/plugins/THREE/postprocessing/BloomPass';


//Extra filter -- film
//---------------------
import FilmPass from '@uixkit/plugins/THREE/postprocessing/FilmPass';
import FilmShader from '@uixkit/plugins/THREE/shaders/FilmShader';


export const THREE_FILMIC_EFF = ( ( module, $, window, document ) => {
	if ( window.THREE_FILMIC_EFF === null ) return false;
	
	
	
    module.THREE_FILMIC_EFF               = module.THREE_FILMIC_EFF || {};
    module.THREE_FILMIC_EFF.version       = '0.0.2';
    module.THREE_FILMIC_EFF.documentReady = function( $ ) {

		
		//Prevent this module from loading in other pages
		if ( $( '#3D-filmic-effects-canvas' ).length == 0 || ! Modernizr.webgl ) return false;
		
		
        let sceneSubjects = []; // Import objects and animations dynamically
		const MainStage = function() {

            const $window          = $( window );
            let	windowWidth        = window.innerWidth,
                windowHeight       = window.innerHeight;


            const rendererCanvasID = '3D-filmic-effects-canvas';




			// Generate one plane geometries mesh to scene
			//-------------------------------------	
			let camera,
				scene,
				lights = [],
				renderer,
                clock = new THREE.Clock();


            let intersectionPlane;
            
            let composer, bloomPass, filmPass;
            
	
			function init() {
		
				
				//=================
				//camera
				camera = new THREE.PerspectiveCamera( 60, windowWidth / windowHeight, 1, 10000 );
				camera.position.set( 0, 0, 100 );
				camera.lookAt(new THREE.Vector3(0, 0, 0));

				
				//=================
				//Scene
				scene = new THREE.Scene();

				
				//=================
				//Lights
				lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
				lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
				lights[ 2 ] = new THREE.DirectionalLight( 0xffffff );

				lights[ 0 ].position.set( 0, 200, 0 );
				lights[ 1 ].position.set( 100, 200, 100 );
				lights[ 2 ].position.set( 120, 200, 0 );
				lights[ 2 ].intensity = 0.6;

				scene.add( lights[ 0 ] );
				scene.add( lights[ 1 ] );
				scene.add( lights[ 2 ] );
				


				//=================
				//WebGL Renderer		
				renderer = new THREE.WebGLRenderer( { 
										canvas   : document.getElementById( rendererCanvasID ), //canvas
										alpha    : true, 
										antialias: true 
									} );
				renderer.setSize( windowWidth, windowHeight );
                renderer.shadowMap.enabled = true;
                renderer.shadowMap.type = THREE.PCFSoftShadowMap;

                //=================
                //add bloom effect
                bloomPass = new THREE.BloomPass(
                    1,    // strength
                    25,   // kernel size
                    4,    // sigma ?
                    256,  // blur render target resolution
                );


                //add film effect
                filmPass = new THREE.FilmPass(
                    0.35,   // noise intensity
                    0.025,  // scanline intensity
                    648,    // scanline count
                    false,  // grayscale
                );



                //-----
                const renderPass = new THREE.RenderPass(scene, camera);
                const effectCopy = new THREE.ShaderPass(THREE.CopyShader);
                effectCopy.renderToScreen = true;


                composer = new THREE.EffectComposer( renderer );
                composer.addPass(renderPass);
                composer.addPass(bloomPass);    
                composer.addPass(filmPass);
                composer.addPass(effectCopy);


				//=================
                const planeGeometry = new THREE.PlaneGeometry(100000, 100000);
                const planeMaterial = new THREE.MeshNormalMaterial({
                    side: THREE.DoubleSide
                });
                intersectionPlane = new THREE.Mesh(planeGeometry, planeMaterial);
                intersectionPlane.visible = false;
                scene.add(intersectionPlane);

                const hoverMaterial = new THREE.MeshNormalMaterial();
                const neutralMaterial = new THREE.MeshLambertMaterial({
                    color: 0xffcccc
                });
                const selectedMaterial = new THREE.MeshBasicMaterial({
                    color: 0x55ff88
                });

                const neutralGeometry = new THREE.IcosahedronGeometry(30, 1);
                const mesh = new THREE.Mesh(neutralGeometry, neutralMaterial);

                mesh.position.x = 0
                mesh.position.y = 0;
                mesh.position.z = 0;

                scene.add(mesh);
      
				//=================
				// Fires when the window changes
				window.addEventListener( 'resize', onWindowResize, false );

				

			}

			function render() {
	
				requestAnimationFrame( render );

				//To set a background color.
				renderer.setClearColor( 0x000000 );	

                
                //push objects
                /*
                @Usage: 

                    function CustomObj( scene ) {

                        const elements = new THREE...;
                        scene.add( elements );

                        this.update = function( time ) {
                            elements.rotation.y = time*0.003;
                        }
                    }       

                    sceneSubjects.push( new CustomObj( MainStage.getScene() ) );  
                */
                for( let i = 0; i < sceneSubjects.length; i++ ) {
                    sceneSubjects[i].update( clock.getElapsedTime()*1 );  
                }
        	

                //render the scene with filter
				composer.render();


			}


			function onWindowResize() {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize( window.innerWidth, window.innerHeight );
			}




			// 
			//-------------------------------------	
			return {
				init                : init,
				render              : render,
				getRendererCanvasID : function () { return rendererCanvasID; },
				getScene            : function () { return scene; },
				getCamera           : function () { return camera; } 
			};


		}();
		
	
		// 
		MainStage.init();
		MainStage.render();

        
        
        
        // Add stars to scene
        //-------------------------------------	
        const starScene = MainStage.getScene();
        const starCamera = MainStage.getCamera();
        
        
        function Stars(scene, terrainSize) {

            const starsGeometry = new THREE.IcosahedronGeometry(terrainSize, 4);

            // geometry deformation
            for (let i=0; i<starsGeometry.vertices.length; i+=1) {
                const scalar = 1+ Math.random() + Math.random();
                starsGeometry.vertices[i].multiplyScalar(scalar)
            }

            const textureLoader = new THREE.TextureLoader();
            textureLoader.setCrossOrigin("anonymous");
            const texture = textureLoader.load( '' );

            const starMaterial = new THREE.PointsMaterial({ map: texture, color: "#fff", size: 20, blending: THREE.AdditiveBlending, transparent: false });
            const stars = new THREE.Points(starsGeometry, starMaterial);
            scene.add(stars);

            this.update = function(time) {
                stars.rotation.y = time*0.13;
            }
        }    
        
        sceneSubjects.push( new Stars(starScene, 150) );
		

		
    };

    module.components.documentReady.push( module.THREE_FILMIC_EFF.documentReady );
	

	return class THREE_FILMIC_EFF {
		constructor() {
			this.module = module;
		}
		
	};
	
})( UixModuleInstance, jQuery, window, document );


